package com.electronic.api;

import com.electronic.exception.ResultCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;

/**
 * 统一API响应结果封装
 * <p>
 * 提供统一的API响应结果封装，包括状态码、成功标志、数据和消息。
 *
 * @param <T> 响应数据类型
 * @author 于洪乾 yhq1913@sina.com
 * ===============================
 * Date：2024年6月15号
 * Time：上午12:45
 * ================================
 */
@Getter
@Setter
@ToString
@NoArgsConstructor
public class R<T> implements Serializable {


    private static final long serialVersionUID = 1L;

    /**
     * 状态码
     */
    private int code;

    /**
     * 是否成功
     */
    private boolean success;

    /**
     * 承载数据
     */
    private T data;

    /**
     * 返回消息
     */
    private String msg;

    /**
     * 错误码
     */
    private String errorCode;

    /**
     * 使用结果码构造响应结果
     *
     * @param resultCode 结果码
     */
    private R(IResultCode resultCode) {
        this(resultCode, null, resultCode.getMessage());
    }

    /**
     * 使用结果码和消息构造响应结果
     *
     * @param resultCode 结果码
     * @param msg        消息
     */
    private R(IResultCode resultCode, String msg) {
        this(resultCode, null, msg);
    }

    /**
     * 使用结果码和数据构造响应结果
     *
     * @param resultCode 结果码
     * @param data       数据
     */
    private R(IResultCode resultCode, T data) {
        this(resultCode, data, resultCode.getMessage());
    }

    /**
     * 使用结果码、数据和消息构造响应结果
     *
     * @param resultCode 结果码
     * @param data       数据
     * @param msg        消息
     */
    private R(IResultCode resultCode, T data, String msg) {
        this(resultCode.getCode(), data, msg, resultCode.getErrorCode());
    }

    /**
     * 使用状态码、数据和消息构造响应结果
     *
     * @param code 状态码
     * @param data 数据
     * @param msg  消息
     */
    private R(int code, T data, String msg, String errorCode) {
        this.code = code;
        this.data = data;
        this.msg = msg;
        this.errorCode = errorCode;
        this.success = ResultCode.SUCC.getCode() == code;
    }



    /**
     * 返回R
     *
     * @param data 数据
     * @param <T>  T 泛型标记
     * @return R
     */
    public static <T> R<T> data(T data) {
        return data(data, "", "");
    }

    /**
     * 返回R
     *
     * @param data 数据
     * @param msg  消息
     * @param <T>  T 泛型标记
     * @return R
     */
    public static <T> R<T> data(T data, String msg, String errorCode) {
        return data(HttpServletResponse.SC_OK, data, msg, errorCode);
    }

    /**
     * 返回R
     *
     * @param code 状态码
     * @param data 数据
     * @param msg  消息
     * @param <T>  T 泛型标记
     * @return R
     */
    public static <T> R<T> data(int code, T data, String msg, String errorCode) {
        return new R<>(code, data, data == null ? "" : msg, errorCode);
    }

    /**
     * 返回R
     *
     * @param msg 消息
     * @param <T> T 泛型标记
     * @return R
     */
//    public static <T> R<T> success(String msg) {
//        return new R<>(ResultCode.SUCC, msg);
//    }

    /**
     * 返回R
     *
     * @param resultCode 业务代码
     * @param <T>        T 泛型标记
     * @return R
     */
    public static <T> R<T> success(IResultCode resultCode) {
        return new R<>(resultCode);
    }

    /**
     * 返回R
     *
     * @param resultCode 业务代码
     * @param msg        消息
     * @param <T>        T 泛型标记
     * @return R
     */
    public static <T> R<T> success(IResultCode resultCode, String msg) {
        return new R<>(resultCode, msg);
    }

    /**
     * 返回R
     *
     * @param msg 消息
     * @param <T> T 泛型标记
     * @return R
     */
//    public static <T> R<T> fail(String msg) {
//        return new R<>(ResultCode.FAIL, msg);
//    }

    /**
     * 返回R
     *
     * @param code 状态码
     * @param msg  消息
     * @param <T>  T 泛型标记
     * @return R
     */
    public static <T> R<T> fail(int code, String msg, String errorCode) {
        return new R<>(code, null, msg, errorCode);
    }

    /**
     * 返回R
     *
     * @param resultCode 业务代码
     * @param <T>        T 泛型标记
     * @return R
     */
    public static <T> R<T> fail(IResultCode resultCode) {
        return new R<>(resultCode);
    }

    /**
     * 返回R
     *
     * @param resultCode 业务代码
     * @param msg        消息
     * @param <T>        T 泛型标记
     * @return R
     */
    public static <T> R<T> fail(IResultCode resultCode, String msg) {
        return new R<>(resultCode, msg);
    }

    /**
     * 返回R
     *
     * @param flag 成功状态
     * @return R
     */
//    public static <T> R<T> status(boolean flag) {
//        return flag ? success("success") : fail("fail");
//    }
}
